package org.jadelyre.core;

import org.jadelyre.core.codec.Codec;
import org.jadelyre.core.exception.JadeException;
import org.jadelyre.core.exception.JadeLyreException;
import org.jadelyre.core.task.EntryQueue;
import org.jadelyre.core.worker.Schedule;
import org.jadelyre.core.worker.Worker;
import org.jadelyre.core.worker.WorkerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.channels.AsynchronousChannelGroup;

public abstract class AbstractJadeLyre implements JadeLyre {

    private static final Logger logger = LoggerFactory.getLogger(AbstractJadeLyre.class);

    protected final JadeLyreConfig jadeLyreConfig;
    protected final Handler handler;
    protected final WorkerFactory workerFactory;
    protected final Worker<Channel> closeWorker;
    protected final Worker<Schedule> scheduledWorker;
    protected final Codec codec;
    protected final AsynchronousChannelGroup asynchronousChannelGroup;
    /**
     * 服务是否运行
     */
    protected volatile boolean started;
    protected Thread shutdownHook;

    public AbstractJadeLyre(Handler handler, Codec codec,JadeLyreConfig jadeLyreConfig) throws JadeLyreException {
        this.jadeLyreConfig = jadeLyreConfig;
        this.handler = handler;
        this.codec = codec;
        workerFactory = new WorkerFactory(jadeLyreConfig);
        asynchronousChannelGroup = createAsynchronousChannelGroup();
        closeWorker = workerFactory.getCloseWorker(this, new EntryQueue<Channel>());
        scheduledWorker = workerFactory.getScheduledWorker(this, new EntryQueue<Schedule>());
    }

    @Override
    public Handler getHandler() {
        return handler;
    }

    @Override
    public Worker<Channel> getCloseWorker() {
        return closeWorker;
    }

    public Worker<Schedule> getScheduledWorker() {
        return scheduledWorker;
    }

    @Override
    public WorkerFactory getWorkerFactory() {
        return workerFactory;
    }

    @Override
    public Codec getCodec() {
        return codec;
    }

    @Override
    public boolean isStarted() {
        return started;
    }

    private AsynchronousChannelGroup createAsynchronousChannelGroup() throws JadeLyreException{
        try {
            return AsynchronousChannelGroup
                    .withThreadPool(ThreadPool.createThreadPool(jadeLyreConfig.getSystemPoolSize()));
        } catch (IOException e) {
            throw new JadeLyreException(e);
        }
    }

    public void setStarted(boolean started) {
        this.started = started;
    }

    @Override
    public JadeLyreConfig getJadeLyreConfig() {
        return jadeLyreConfig;
    }

    protected void addShutdownHook() {
        if (shutdownHook != null) {
            return;
        }
        shutdownHook = new Thread(() -> {
            if (logger.isInfoEnabled()) {
                logger.info("Run shutdown hook now.");
            }
            stop();
        }, "AbstractJadeLyreShutdownHook");
        Runtime.getRuntime().addShutdownHook(shutdownHook);
    }
}
